var criteria = 
{ Name: "ESG Risk Rating", Level2: [
    { Name: "Overall ESG Risk Rating", Level3: [
        { Name: "ESG Risk Rating", Level4: [{ Name: "ESG Risk Rating", CriteriaEntityField: "ESG Risk Rating", IsScreenable: true, CriteriaType: 6 }] },
        { Name: "ESG Risk Category", Level4: [{ Name: "ESG Risk Category", CriteriaEntityField: "ESG Risk Category", IsScreenable: true, CriteriaType: 25  }] },
        { Name: "ESG Risk Rating Rank", Level4: [{ Name: "ESG Risk Rating Rank", CriteriaEntityField: "ESG Risk Rating Rank", IsScreenable: true, HasFullRangeChart: false, CriteriaType: 6  }] },
        { Name: "ESG Risk Rating Percentile", Level4: [{ Name: "ESG Risk Rating Percentile", CriteriaEntityField: "ESG Risk Rating Percentile", IsScreenable: true, CriteriaType: 6  }] },
        { Name: "Management Score", Level4: [{ Name: "Management Score", CriteriaEntityField: "ESG Management Score", IsScreenable: true, CriteriaType: 6  }] },
        { Name: "Exposure Score", Level4: [{ Name: "Exposure Score", CriteriaEntityField: "ESG Exposure Score", IsScreenable: true, CriteriaType: 6  }] },
        { Name: "Managed Risk", Level4: [{ Name: "Managed Risk", CriteriaEntityField: "Managed Risk", IsScreenable: true, CriteriaType: 6  }] }
    ]},
    { Name: "Corporate Governance", Level3: [
        { Name: "Corporate Governance - ESG Risk Rating", Level4: [{ Name: "Corporate Governance - ESG Risk Rating", CriteriaEntityField: "Issue - Corporate Governance-ESG Risk Rating", IsScreenable: true, CriteriaType: 6 },
                                            {Name: "Corporate Governance-Weight", CriteriaEntityField: "Issue - Corporate Governance-Weight", IsScreenable: false}] },
        { Name: "Corporate Governance-ESG Risk Category", Level4: [{ Name: "Corporate Governance-ESG Risk Category", CriteriaEntityField: "Issue - Corporate Governance-Risk Category", IsScreenable: true, CriteriaType: 25  }] },
        { Name: "Corporate Governance-Management Score", Level4: [{ Name: "Corporate Governance-Management Score", CriteriaEntityField: "Issue - Corporate Governance-Management Score", IsScreenable: true, CriteriaType: 6  }] },
        { Name: "Corporate Governance-Exposure Score", Level4: [{ Name: "Corporate Governance-Exposure Score", CriteriaEntityField: "Issue - Corporate Governance-Exposure Score", IsScreenable: true, CriteriaType: 6  }] },
        { Name: "Corporate Governance-Managed Risk", Level4: [{ Name: "Corporate Governance-Managed Risk", CriteriaEntityField: "Issue - Corporate Governance-Managed Risk", IsScreenable: true, CriteriaType: 6  }] }
    ]},
]};
var issueCriteria = { Name: "GenericMEI", Level3: [
        { Name: "ESG Risk Rating", Level4: [{ Name: "-ESG Risk Rating", CriteriaEntityField: "-ESG Risk Rating", IsScreenable: true, CriteriaType: 6, MaxValue: 20 },
                                            {Name: "-Weight", CriteriaEntityField: "-Weight", IsScreenable: false}] },
        { Name: "ESG Risk Category", Level4: [{ Name: "-ESG Risk Category", CriteriaEntityField: "-Risk Category", IsScreenable: true, CriteriaType: 25  }] },
        { Name: "Management Score", Level4: [{ Name: "-Management Score", CriteriaEntityField: "-Management Score", IsScreenable: true, CriteriaType: 6  }] },
        { Name: "Exposure Score", Level4: [{ Name: "-Exposure Score", CriteriaEntityField: "-Exposure Score", IsScreenable: true, CriteriaType: 6, MaxValue: 20  },
                                                {Name: "-Subindustry Exposure Score", CriteriaEntityField: "-Subindustry Exposure Score", IsScreenable: false}] },
        { Name: "Managed Risk", Level4: [{ Name: "-Managed Risk", CriteriaEntityField: "-Managed Risk", IsScreenable: true, CriteriaType: 6, MaxValue: 20  }] },
        { Name: "Beta", Level4: [{ Name: "-Beta", CriteriaEntityField: "-Issue Beta", IsScreenable: true, CriteriaType: 6, MaxValue: 2  }] }
    ]};
var MeiList = ["Access to Basic Services","Animal Welfare","Animal Welfare - Supply Chain","Bribery and Corruption","Bribery and Corruption - Supply Chain","Business Ethics","Business Ethics - Supply Chain",
            "Community Relations","Community Relations - Supply Chain","Data Privacy and Security","Emissions, Effluents and Waste","Emissions, Effluents and Waste - Supply Chain","Carbon - Own Operations",
            "Carbon - Supply Chain","Carbon - Products and Services","E&S Impact of Products and Services","Human Rights","Human Rights - Supply Chain","Human Capital","Labour Relations - Supply Chain",
            "Land Use and Biodiversity","Land Use and Biodiversity - Supply Chain","Occupational Health and Safety","Occupational Health and Safety - Supply Chain","ESG Integration - Financials",
            "Product Governance","Resilience","Resource Use","Resource Use - Supply Chain"];

function uuid() {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
    }
    return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4();
}

function HexToBase64(hex) {
    var base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var base64 = "";
    var group;
    for (var i = 0; i < 30; i += 6) {
        group = parseInt(hex.substr(i, 6), 16);
        base64 += base64Digits[(group >> 18) & 0x3f];
        base64 += base64Digits[(group >> 12) & 0x3f];
        base64 += base64Digits[(group >> 6) & 0x3f];
        base64 += base64Digits[group & 0x3f];
    }
    group = parseInt(hex.substr(30, 2), 16);
    base64 += base64Digits[(group >> 2) & 0x3f];
    base64 += base64Digits[(group << 4) & 0x3f];
    base64 += "==";
    return base64;
}

function NUUID(uuid) {
    var hex = uuid.replace(/[{}-]/g, ""); // remove extra characters
    var a = hex.substr(6, 2) + hex.substr(4, 2) + hex.substr(2, 2) + hex.substr(0, 2);
    var b = hex.substr(10, 2) + hex.substr(8, 2);
    var c = hex.substr(14, 2) + hex.substr(12, 2);
    var d = hex.substr(16, 16);
    hex = a + b + c + d;
    var base64 = HexToBase64(hex);
    return new BinData(3, base64);
}

function processLevel1(criteria) {
    if (!db.CriteriaLevel1.findOne({ Name: criteria.Name })) {
        db.CriteriaLevel1.insert({
            _id: NUUID(uuid()),
            Name: criteria.Name,
            ShortName: 'RiskRatings',
            Order: NumberInt(15)
        });
    }

    var criteriaLevel1Id = db.CriteriaLevel1.findOne({ Name: criteria.Name })._id;

    criteria.Level2.forEach(function (criteria, index) {
        processLevel2(criteriaLevel1Id, criteria, index);
    });

    addMeiCriteria(criteriaLevel1Id);
}

function addMeiCriteria(criteriaLevel1Id) 
{
    if (!db.CriteriaLevel2.findOne({ Name: "Material E&S Issues" })) {
        db.CriteriaLevel2.insert({
            _id: NUUID(uuid()),
            CriteriaLevel1Id: criteriaLevel1Id,
            UniverseFeature: NumberInt(18),
            Name: "Material E&S Issues",
            ShortName: 'RiskRatings',
            Order: NumberInt(2)
        });
    }
    
    var criteriaLevel2Id = db.CriteriaLevel2.findOne({ Name: "Material E&S Issues" })._id;
    var meiCriteriaLength = issueCriteria.Level3.length;
    var meiNo = MeiList.length;
    
    var meiIndex = meiCriteriaLength * meiNo;
    MeiList.forEach(function(MeiName)
    {
        issueCriteria.Level3.forEach(function (issueCriteria, index) 
        {
            processLevel3Mei(criteriaLevel2Id, issueCriteria, meiIndex-index, MeiName);
        });
        meiIndex -= meiCriteriaLength;
    });
}

function processLevel2(criteriaLevel1Id, criteria, index) {
    if (!db.CriteriaLevel2.findOne({ Name: criteria.Name })) {
        db.CriteriaLevel2.insert({
            _id: NUUID(uuid()),
            CriteriaLevel1Id: criteriaLevel1Id,
            UniverseFeature: NumberInt(18),
            Name: criteria.Name,
            ShortName: 'RiskRatings',
            Order: NumberInt(index)
        });
    }

    var criteriaLevel2Id = db.CriteriaLevel2.findOne({ Name: criteria.Name })._id;
    var length = criteria.Level3.length;

    criteria.Level3.forEach(function (criteria, index) {
        processLevel3(criteriaLevel2Id, criteria, length - index);
    });
}

function processLevel3Mei(criteriaLevel2Id, issueCriteria, index, prefix) {
    if (!db.CriteriaLevel3.findOne({ Name: issueCriteria.Name, CriteriaLevel2Id: criteriaLevel2Id, Category: prefix })) 
    {
        db.CriteriaLevel3.insert({
            _id: NUUID(uuid()),
            Name: issueCriteria.Name,
            ShortName: issueCriteria.Name,
            Order: NumberInt(index),
            CriteriaLevel2Id: criteriaLevel2Id,
            Category: prefix,
        });
    }

    var criteriaLevel3Id = db.CriteriaLevel3.findOne({ Name: issueCriteria.Name, CriteriaLevel2Id: criteriaLevel2Id, Category: prefix })._id;

    issueCriteria.Level4.forEach(function (issueCriteria) {
        processLevel4Mei(criteriaLevel2Id, criteriaLevel3Id, issueCriteria, index, prefix);
    });
}


function processLevel3(criteriaLevel2Id, criteria, index) {
    if (!db.CriteriaLevel3.findOne({ Name: criteria.Name, CriteriaLevel2Id: criteriaLevel2Id })) 
    {
        db.CriteriaLevel3.insert({
            _id: NUUID(uuid()),
            Name: criteria.Name,
            ShortName: criteria.Name,
            Order: NumberInt(index),
            CriteriaLevel2Id: criteriaLevel2Id,
            Category: "None",
        });
    }

    var criteriaLevel3Id = db.CriteriaLevel3.findOne({ Name: criteria.Name, CriteriaLevel2Id: criteriaLevel2Id })._id;
    
    criteria.Level4.forEach(function (criteria) {
        processLevel4(criteriaLevel2Id, criteriaLevel3Id, criteria, index);
    });
}

function processLevel4Mei(criteriaLevel2Id, criteriaLevel3Id, issueCriteria, index, prefix) {
    
    if (!db.TemplateCriteria.findOne({ Name: prefix+issueCriteria.Name, CriteriaLevel2Id: criteriaLevel2Id })) {
        if(issueCriteria.MaxValue)
        db.TemplateCriteria.insert({
            _id: NUUID(uuid()),
            Name: "Issue - "+prefix+issueCriteria.Name,
            CriteriaEntity: null,
            CriteriaEntityField: "Issue - "+prefix+issueCriteria.CriteriaEntityField,
            CriteriaType: NumberInt(issueCriteria.CriteriaType),
            CriteriaLevel2Id: criteriaLevel2Id,
            CriteriaLevel3Id: criteriaLevel3Id,
            IsScreenable: issueCriteria.IsScreenable,
            ResearchProducts: ["RiskRating"],
            GetsValueFromParent: true,
            HasFullRangeChart: issueCriteria.HasFullRangeChart==false? false : true,
            MaxValue: NumberInt(issueCriteria.MaxValue),
        });
        else
        db.TemplateCriteria.insert({
            _id: NUUID(uuid()),
            Name: "Issue - "+prefix+issueCriteria.Name,
            CriteriaEntity: null,
            CriteriaEntityField: "Issue - "+prefix+issueCriteria.CriteriaEntityField,
            CriteriaType: NumberInt(issueCriteria.CriteriaType),
            CriteriaLevel2Id: criteriaLevel2Id,
            CriteriaLevel3Id: criteriaLevel3Id,
            IsScreenable: issueCriteria.IsScreenable,
            ResearchProducts: ["RiskRating"],
            GetsValueFromParent: true,
            HasFullRangeChart: issueCriteria.HasFullRangeChart==false? false : true,
        });
    }
}

function processLevel4(criteriaLevel2Id, criteriaLevel3Id, criteria, index) {
    if (!db.TemplateCriteria.findOne({ Name: criteria.Name, CriteriaLevel2Id: criteriaLevel2Id })) {
        if(criteria.MaxValue)
        db.TemplateCriteria.insert({
            _id: NUUID(uuid()),
            Name: criteria.Name,
            CriteriaEntity: null,
            CriteriaEntityField: criteria.CriteriaEntityField,
            CriteriaType: NumberInt(criteria.CriteriaType),
            CriteriaLevel2Id: criteriaLevel2Id,
            CriteriaLevel3Id: criteriaLevel3Id,
            IsScreenable: criteria.IsScreenable,
            ResearchProducts: ["RiskRating"],
            GetsValueFromParent: true,
            HasFullRangeChart: criteria.HasFullRangeChart==false? false : true,
            MaxValue: NumberInt(criteria.MaxValue),
       });
        else
        db.TemplateCriteria.insert({
            _id: NUUID(uuid()),
            Name: criteria.Name,
            CriteriaEntity: null,
            CriteriaEntityField: criteria.CriteriaEntityField,
            CriteriaType: NumberInt(criteria.CriteriaType),
            CriteriaLevel2Id: criteriaLevel2Id,
            CriteriaLevel3Id: criteriaLevel3Id,
            IsScreenable: criteria.IsScreenable,
            ResearchProducts: ["RiskRating"],
            GetsValueFromParent: true,
            HasFullRangeChart: criteria.HasFullRangeChart==false? false : true,
       });
    }
}

processLevel1(criteria);    